package cn.itcast.dao.impl;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import cn.itcast.anno.PrimaryKey;
import cn.itcast.dao.IBaseDao;

/**
 * 所有dao的通用操作，希望所有的dao都继承此类
 * @author Jie.Yuan
 *
 * @param <T>
 */
public class BaseDao<T> implements IBaseDao<T> {

	// 当前操作的实际的bean类型
	private Class<T> clazz;
	// 获取类名称
	private String className;
	//获取类的主键
	private String primaryKey;
	
	//反射泛型
	@SuppressWarnings("unchecked")
	public BaseDao() {
		Type type = this.getClass().getGenericSuperclass();
		//转换为参数化类型
		ParameterizedType pt = (ParameterizedType) type;
		// 得到实际类型
		Type[] types = pt.getActualTypeArguments();
		// 获取实际类型
		clazz = (Class<T>) types[0];
		
		className = clazz.getSimpleName();
		
		Field[] field = clazz.getDeclaredFields();
		for (Field f : field) {
			boolean isFExist = f.isAnnotationPresent(PrimaryKey.class);
			if(isFExist){
				PrimaryKey p = f.getAnnotation(PrimaryKey.class);
				primaryKey = p.primaryKey();
			}
		}
	}
	
	// 容器注入
	private SessionFactory sessionFactory;
	
	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	@Override
	public void save(T t) {
		sessionFactory.getCurrentSession().save(t);
	}

	@Override
	public void update(T t) {
		sessionFactory.getCurrentSession().update(t);
	}

	@Override
	public void delete(int id) {
		Session session = sessionFactory.getCurrentSession();
		Query q = session.createQuery("delete from "+className+" where "+primaryKey+" = ?");
		q.setParameter(0, id);
		q.executeUpdate();
	}

	@SuppressWarnings("unchecked")
	@Override
	public T findById(int id) {
		return (T) sessionFactory.getCurrentSession().get(clazz, id);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> getAll() {
		return sessionFactory.getCurrentSession().createQuery("from " + className).list();
	}

}
